package com.yfp.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfp.client.domain.*;
import com.yfp.client.domain.*;
import com.yfp.client.domain.dto.ActivitySignInsExchangeRecordReqDTO;
import com.yfp.client.domain.vo.ActivitySignInsExchangeRecordVO;
import com.yfp.client.domain.vo.ActivitySignInsRulesVO;
import com.yfp.client.domain.vo.ActivitySignInsVO;
import com.yfp.client.enums.ActivitySignInsRewardTypeEnums;
import com.yfp.client.enums.ActivitySignInsStatusEnums;
import com.yfp.client.mapper.ActivitySignInsMapper;
import com.yfp.client.service.*;
import com.yfp.client.service.*;
import com.yfp.client.util.RedisDistributedLock;
import com.yfp.client.util.SecurityUtils;
import com.yfp.common.core.constant.CacheConstants;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 *
 * @description 针对表【activity_sign_ins(打卡管理主表)】的数据库操作Service实现
 * @createDate 2025-01-03 17:46:13
 */
@Slf4j
@Service
public class ActivitySignInsServiceImpl extends ServiceImpl<ActivitySignInsMapper, ActivitySignIns> implements ActivitySignInsService {

    @Resource
    public RedisTemplate redisTemplate;
    @Resource
    private ActivitySignInsMapper activitySignInsMapper;
    @Resource
    private ActivitySignInsRulesService activitySignInsRulesService;
    @Resource
    private ActivitySignInsClientsService activitySignInsClientsService;
    @Resource
    private ActivitySignInsClientRecordsService activitySignInsClientRecordsService;
    @Resource
    private MarCouponService marCouponService;
    @Resource
    private ClientCouponService clientCouponService;
    @Resource
    private MarCouponPackService marCouponPackService;

    @Override
    public ActivitySignInsVO getActivityDetails(Long activitySignInsId, String cityName) {

        Long ongoingActivitySignInsId = null;
        if (Objects.isNull(activitySignInsId)) {
            ongoingActivitySignInsId = activitySignInsMapper.getOngoingActivitySignIns(ActivitySignInsStatusEnums.ONGOING.getCode(), cityName);
        } else {
            ongoingActivitySignInsId = activitySignInsMapper.selectByIdAndCityName(activitySignInsId, cityName);
        }

        if (ongoingActivitySignInsId == null) {
            return null;
        }
        ActivitySignInsVO info = this.getInfo(ongoingActivitySignInsId);

        // 填充用户已累计打卡N次数、底部按钮状态、用户是否已经领取
        info = this.fillActivitySignInsInfo(info);

        return info;
    }

    @Override
    public ActivitySignInsVO getInfo(Long id) {
        ActivitySignIns activitySignIns = activitySignInsMapper.selectById(id);
        List<ActivitySignInsRules> activitySignInsRules = activitySignInsRulesService.listByActivitySignInsId(id);

        ActivitySignInsVO activitySignInsVO = BeanUtil.toBean(activitySignIns, ActivitySignInsVO.class);
        List<ActivitySignInsRulesVO> activitySignInsRulesVOS = activitySignInsRules.stream().map(item -> {
            ActivitySignInsRulesVO activitySignInsRulesVO = BeanUtil.toBean(item, ActivitySignInsRulesVO.class);
            // 奖品Name
            activitySignInsRulesVO.setRewardName(this.getRewardName(item.getRewardId(), item.getRewardType()));
            return activitySignInsRulesVO;
        }).toList();

        activitySignInsVO.setActivitySignInsRulesVOList(activitySignInsRulesVOS);
        return activitySignInsVO;
    }

    @Override
    public String getRewardName(Long rewardId, Integer rewardType) {
        List<Integer> marCouponList = Arrays.asList(ActivitySignInsRewardTypeEnums.COUPON.getCode(), ActivitySignInsRewardTypeEnums.ENTITY_GOODS.getCode());
        List<Integer> marCouponPackList = Arrays.asList(ActivitySignInsRewardTypeEnums.GIFT_PACKAGE.getCode());

        if (CollUtil.contains(marCouponList, rewardType)) {
            MarCoupon marCoupon = marCouponService.findById(rewardId);
            return marCoupon.getCouponName();
        } else if (CollUtil.contains(marCouponPackList, rewardType)) {
            MarCouponPack couponPack = marCouponPackService.findById(rewardId);
            return couponPack.getPackName();
        }

        return "";
    }

    @Override
    public void joinActivity(Long activitySignInsId) {
        ActivitySignIns activitySignIns = activitySignInsMapper.selectById(activitySignInsId);
        // Assert.isTrue(DateUtil.isIn(DateUtil.date(),activitySignIns.getStartTime(),activitySignIns.getEndTime()), "活动已结束");
        Assert.isTrue(ActivitySignInsStatusEnums.ONGOING.getCode().equals(activitySignIns.getStatus()), "活动已结束");

        // 校验是否已经参加
        Assert.isFalse(activitySignInsClientsService.joined(activitySignInsId), "您已参加该活动");

        activitySignInsClientsService.joinActivity(activitySignInsId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ActivitySignInsRulesVO receiveReward(Long activitySignInsId) {
        ActivitySignIns activitySignIns = activitySignInsMapper.selectById(activitySignInsId);
        // Assert.isTrue(DateUtil.isIn(DateUtil.date(),activitySignIns.getStartTime(),activitySignIns.getEndTime()), "活动已结束");
        Assert.isTrue(ActivitySignInsStatusEnums.ONGOING.getCode().equals(activitySignIns.getStatus()), "活动已结束");

        // 校验是否已经参加
        Assert.isTrue(activitySignInsClientsService.joined(activitySignInsId), "您未参加该活动");

        // 获取可以领取的打卡规则
        List<ActivitySignInsRules> activitySignInsRulesList = activitySignInsRulesService.listByActivitySignInsId(activitySignInsId);
        Long activitySignInsRulesId = activitySignInsClientRecordsService.canReceiveReward2(activitySignInsId, activitySignInsRulesList);
        if (Objects.isNull(activitySignInsRulesId)) {
            return null;
        }

        ActivitySignInsRules activitySignInsRules = null;

        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisTemplate, CacheConstants.ACTIVITY_SIGN_INS_PRIZE_REMAINING_STOCK_LOCK_KEY, 10);
        try {
            // 加锁
            redisDistributedLock.lock();

            // 校验库存
            Boolean checkStock = activitySignInsRulesService.checkStock(activitySignInsRulesId);
            if (!checkStock) {
                return null;
            }

            activitySignInsRules = activitySignInsClientRecordsService.receiveReward(activitySignInsRulesId);
            if (Objects.isNull(activitySignInsRules)) {
                return null;
            }

            // 减少库存
            activitySignInsRulesService.salesDeduction(activitySignInsRulesId);
        } catch (Exception e) {
            log.info("领券异常：{}", e);
            throw new RuntimeException("领券异常");
        } finally {
            redisDistributedLock.unlock();
        }

        ActivitySignInsRulesVO activitySignInsRulesVO = BeanUtil.toBean(activitySignInsRules, ActivitySignInsRulesVO.class);
        activitySignInsRulesVO.setRewardName(this.getRewardName(activitySignInsRulesVO.getRewardId(), activitySignInsRulesVO.getRewardType()));
        activitySignInsRulesVO.setIsReceive(1);
        return activitySignInsRulesVO;
    }

    @Override
    public List<ActivitySignInsExchangeRecordVO> exchangeRecord(ActivitySignInsExchangeRecordReqDTO exchangeRecordReqDTO) {
        List<ActivitySignInsClientRecords> activitySignInsClientRecords = activitySignInsClientRecordsService.exchangeRecord(exchangeRecordReqDTO);
        List<Long> activitySignInsClientRecordsIdList = activitySignInsClientRecords.stream().map(ActivitySignInsClientRecords::getId).toList();

        List<ClientCoupon> clientCouponList = clientCouponService.getActivitySignInsClientRecordsById(SecurityUtils.getClientId(), activitySignInsClientRecordsIdList);
        return clientCouponList.stream().map(item -> BeanUtil.toBean(item, ActivitySignInsExchangeRecordVO.class)).toList();
    }

    @Override
    public ActivitySignInsVO fillActivitySignInsInfo(ActivitySignInsVO info) {
        ActivitySignInsVO activitySignInsVO = BeanUtil.toBean(info, ActivitySignInsVO.class);

        // 填充用户已累计打卡N次数
        ActivitySignInsClients activitySignInsClients = activitySignInsClientsService.getByClientAndId(activitySignInsVO.getId());
        if (Objects.isNull(activitySignInsClients)) {
            activitySignInsVO.setCheckedCount(0);
        } else {
            activitySignInsVO.setCheckedCount(activitySignInsClients.getTotalSignIn());
        }

        // 填充底部按钮状态[1:立即参与灰、2:立即参与、3:立即领取灰、4:立即领取、5:恭喜完成全部打卡灰]
        Integer buttonStatus = this.fillButtonStatus(activitySignInsVO);
        activitySignInsVO.setButtonStatus(buttonStatus);

        // 填充用户是否已经领取
        List<ActivitySignInsRulesVO> activitySignInsRulesVOS = activitySignInsClientRecordsService.fillIsReceive(activitySignInsVO.getId(), activitySignInsVO.getActivitySignInsRulesVOList());
        activitySignInsVO.setActivitySignInsRulesVOList(activitySignInsRulesVOS);

        return activitySignInsVO;
    }

    @Override
    public Integer fillButtonStatus(ActivitySignInsVO activitySignInsVO) {
        // [1:立即参与灰、2:立即参与、3:立即领取灰、4:立即领取、5:恭喜完成全部打卡灰]
        ActivitySignIns activitySignIns = this.getById(activitySignInsVO.getId());


        Boolean ongoing = ActivitySignInsStatusEnums.ONGOING.getCode().equals(activitySignIns.getStatus());
        Boolean joined = activitySignInsClientsService.joined(activitySignInsVO.getId());
        if (!ongoing && joined) {
            return 1;
        }
        if (ongoing && !joined) {
            return 2;
        }
        // 计算是否已全部领取奖品
        Boolean allRewardsReceived = activitySignInsClientRecordsService.isAllRewardsReceived(activitySignInsVO.getId(), activitySignInsVO.getActivitySignInsRulesVOList());
        if (allRewardsReceived && ongoing && joined) {
            return 5;
        }
        // 计算是否可以领取奖品
        Boolean canReceiveReward = activitySignInsClientRecordsService.canReceiveReward(activitySignInsVO.getId(), activitySignInsVO.getActivitySignInsRulesVOList());
        if (!canReceiveReward && ongoing && joined) {
            return 3;
        }
        if (canReceiveReward && ongoing && joined) {
            return 4;
        }
        return 0;
    }
}




